#pragma once

#include <string>
#include <string>
#include <queue>
#include <vector>
#include <memory>
#include "Log.hpp"
#include "Mutex.hpp"
#include "Cond.hpp"
#include "Thread.hpp"
namespace ThreadPoolMoudule
{

    using namespace LogMoudule;
    using namespace CondMoudule;
    using namespace MutexMoudle;
    using namespace ThreadMoudule;

    // 测试方法
    void Test()
    {
        while (true)
        {
            sleep(1);
            LOG(LogLevel::DEBUG) << "我是一个测试方法";
        }
    }

    const static int defaultnum = 5;
    using thread_t = std::shared_ptr<Thread>;

    template <typename T>
    class ThreadPool
    {
    private:
        bool IsEmpty() { return _taskq.empty(); }
        void HeadlerTask(std::string name)
        {
            while (true)
            {
                // 拿任务
                T t;
                {
                    LockGuard lockguard(_lock);
                    while (IsEmpty()&&_isrunning)
                    {
                        _wait_num++;
                        _cond.Wait(_lock);
                        _wait_num--;
                    }
                    if(IsEmpty()&&!_isrunning) break;
                    t = _taskq.front();
                    _taskq.pop();
                }
                // 处理任务
                t();
            }
            LOG(LogLevel::INFO)<<"线程: "<<name<<"...停止成功";
        }

    public:
        static ThreadPool<T> *getInstance()
        {
            if (instance == NULL)
            {
                LockGuard lockguard(mutex);
                if (instance == NULL)
                {
                    LOG(LogLevel::INFO) << "单例首次被执行，需要加载对象...";
                    instance = new ThreadPool<T>();
                    instance->Start();
                }
            }

            return instance;
        }
        ThreadPool(int num = defaultnum) : _num(num), _wait_num(0), _isrunning(false)
        {
            for (int i = 0; i < _num; i++)
            {
                _threads.push_back(std::make_shared<Thread>(std::bind(&ThreadPool::HeadlerTask, this, std::placeholders::_1)));
                LOG(LogLevel::DEBUG) << "创建成功: " << _threads.back()->GetName() << "...成功";
            }
        }
        void Equeue(T in)
        {
            LockGuard lockguard(_lock);
            if(!_isrunning) return;
            _taskq.push(in);
            if (_wait_num > 0)
            {
                _cond.Nodify();
            }
        }
        void Start() // 启动线程
        {
            if(_isrunning) return;
            _isrunning=true;
            for (auto &thread_ptr : _threads)
            {
                if (!thread_ptr->Start())
                    LOG(LogLevel::DEBUG) << "启动失败: " << thread_ptr->GetName() << "...失败";
                else
                    LOG(LogLevel::DEBUG) << "启动成功: " << thread_ptr->GetName() << "...成功";
            }
        }
        void Stop()
        {
            _isrunning = false;
            // 1.还有任务未处理
            if (IsEmpty())
                _cond.NodiftAll();
            // 2.线程未被唤醒
        }
        void Wait() // 回收线程
        {
            for (auto &thread_ptr : _threads)
            {
                if (thread_ptr->Join())
                    LOG(LogLevel::DEBUG) << "回收成功: " << thread_ptr->GetName() << "...成功";
                else
                    LOG(LogLevel::DEBUG) << "回收失败: " << thread_ptr->GetName() << "...失败";
            }
        }
        ~ThreadPool()
        {
        }

    private:
        std::vector<thread_t> _threads; // 线程池
        int _num;                       // 初始线程数量
        std::queue<T> _taskq;           // 任务队列
        Cond _cond;                     // 条件变量
        int _wait_num;                  // 等待线程数量
        Mutex _lock;                    // 锁
        bool _isrunning;                // 判断进程池是否正在运行

         static ThreadPool<T> *instance;
        static Mutex mutex; // 只用来保护单例
    };


    template <typename T>
    ThreadPool<T> *ThreadPool<T>::instance = NULL;
    template <typename T>
    Mutex ThreadPool<T>::mutex; // 只用来保护单例
}